#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include "utils.h"

typedef struct {
    int    id;
    double value;
} Data;

int main(int argc, char** argv) {
    MPI_Init(&argc, &argv);

    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (size < 2) {
        fprintf(stderr, "Size must be greater than 1\n");
        MPI_Abort(MPI_COMM_WORLD, 1);
    }

    Data data;
    if (rank == 0) {
        data.id    = 123;
        data.value = 3.14;
    }

    // Packing
    int buffer_size = 2 * sizeof(int) + sizeof(double);
    void* buffer    = malloc(buffer_size);
    int position    = 0;

    if (rank == 0) {
        MPI_Pack(&data.id,    1, MPI_INT,    buffer, buffer_size, &position, MPI_COMM_WORLD);
        // INFO("0 rank = %d, position = %d\n", rank, position);       //! 4
        MPI_Pack(&data.value, 1, MPI_DOUBLE, buffer, buffer_size, &position, MPI_COMM_WORLD);
        // INFO("1 rank = %d, position = %d\n", rank, position);       //! 12
    }

    // Sending
    if (rank == 0) {
        MPI_Send(buffer, position, MPI_PACKED, 1, 0, MPI_COMM_WORLD);  //! 应该是按字节统计了
    } else if (rank == 1) {                                            //! 接收的数量大于发送的数量
        MPI_Recv(buffer, buffer_size, MPI_PACKED, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    }

    // Unpacking
    if (rank == 1) {
        position = 0;
        MPI_Unpack(buffer, buffer_size, &position, &data.id, 1, MPI_INT, MPI_COMM_WORLD);
        // INFO("0 rank = %d, position = %d\n", rank, position);       //! 4
        MPI_Unpack(buffer, buffer_size, &position, &data.value, 1, MPI_DOUBLE, MPI_COMM_WORLD);
        // INFO("0 rank = %d, position = %d\n", rank, position);       //! 12

        printf("Received data: id = %d, value = %f\n", data.id, data.value);
    }

    free(buffer);
    MPI_Finalize();
    return 0;
}